//
// Created by martin on 2/9/22.
//

#ifndef MUDUO_SOCKETSOPS_H
#define MUDUO_SOCKETSOPS_H

#include <arpa/inet.h>

namespace muduo
{
namespace net
{
namespace sockets
{

// 基础的sock fd操作

/* 包裹socket(2), 创建非阻塞sockfd. 失败终止程序(LOG_SYSFATAL) */
int createNonblockingOrDie(sa_family_t family);

/* 包裹connect(2), 连接指定对端地址(addr) */
int connect(int sockfd, const struct sockaddr* addr);
/* 包裹bind(2), 绑定本地sockfd与本地ip地址addr. 失败终止程序(LOG_SYSFATAL) */
void bindOrDie(int sockfd, const struct sockaddr* addr);
/* 包裹bind(2), 绑定本地sockfd与本地ip地址addr. 失败返回-1; 成功返回0 */
int bindNoDie(int sockfd, const struct sockaddr* addr);
/* 包裹listen(2), 监听本地sockfd. 失败终止程序(LOG_SYSFATAL) */
void listenOrDie(int sockfd);
/* 包裹listen(2), 监听本地sockfd. 失败返回-1; 成功返回0 */
int listenNoDie(int sockfd);
/* 包裹accept(2)/accept4(2), 接受客户端请求连接, 返回连接sockfd */
int accept(int sockfd, struct sockaddr_in6* addr);
/* 包裹read(2), 从sockfd读取数据, 存放到数组buf[count] */
ssize_t read(int sockfd, void* buf, size_t count);
/* 包裹readv(2), 从sockfd读取数据, 存放到不连续内存iov[iovcnt]中 */
ssize_t readv(int sockfd, const struct iovec* iov, int iovcnt);
/* 包裹write(2), 将buf[count]中的数据写到sockfd连接 */
ssize_t write(int sockfd, const void* buf, size_t count);
/* 包裹close(2), 关闭sockfd */
void close(int sockfd);
/* 包裹shutdown(8), 关闭连接写方向 */
void shutdownWrite(int sockfd);

void fflush(int sockfd);

// 便于交互的转换操作

/* 将地址addr中包含的ip地址+port信息转换为C风格字符串, 存放到数组buf[fileSize] */
void toIpPort(char* buf, size_t size, const struct sockaddr* addr);
/* 将地址addr中包含的ip地址转换为C风格字符串, 存放到数组buf[fileSize] */
void toIp(char* buf, size_t size, const struct sockaddr* addr);

/* 将参数ip, port转换为sockaddr_in结构的addr */
void fromIpPort(const char* ip, uint16_t port, struct sockaddr_in* addr);
/* 将参数ip, port转换为sockaddr_in6结构的addr */
void fromIpPort(const char* ip, uint16_t port, struct sockaddr_in6* addr);

// 地址类型转型

/* const sockaddr_in转型为const sockaddr　*/
const struct sockaddr* sockaddr_cast(const struct sockaddr_in* addr);
/* const sockaddr_in6转型为const sockaddr　*/
const struct sockaddr* sockaddr_cast(const struct sockaddr_in6* addr);
/* sockaddr_in6转型为sockaddr　*/
struct sockaddr* sockaddr_cast(struct sockaddr_in6* addr);
/* const sockaddr转型为const sockaddr_in */
const struct sockaddr_in* sockaddr_in_cast(const struct sockaddr* addr);
/* const sockaddr转型为const sockaddr_in6 */
const struct sockaddr_in6* sockaddr_in6_cast(const struct sockaddr* addr);

// 协议栈信息

/* 获取tcp/ip协议栈错误 */
int getSocketError(int sockfd);
/* 获取sockfd对应的本地地址 */
struct sockaddr_in6 getLocalAddr(int sockfd);
/* 获取sockfd对应的对端地址 */
struct sockaddr_in6 getPeerAddr(int sockfd);
/* 判断sockfd是否为自连接 */
bool isSelfConnect(int sockfd);

} // namespace sockets
} // namespace net
} // namespace muduo

#endif //MUDUO_SOCKETSOPS_H
